The way that locks are implemented depends upon the hardware architecture of the computer using them. On multiprocessor computers, locks are busy-wait locks, so the processor continually tries to acquire the lock until it succeeds. This implementation makes sense only on multiprocessor systems, in which one processor can release the lock while another processor is "spinning," trying to acquire the lock. On single processor systems, locks are implemented using the same algorithm as semaphores--that is, processes waiting to acquire a lock may be put to sleep until the lock is released by another process.
The following functions are provided for creating and controlling locks:
usnewlock(3P) | Allocate a lock in a specified arena. |
usfreelock(3P) | Release lock memory (does not release any process waiting on the lock). |
usinitlock(3P) | Reset a lock and its metering information (does not release any process waiting on the lock). |
usctllock(3P) | Fetch and reset semaphore metering information or debugging information. |
usdumplock(3P) | Dump lock metering information to a file. |
You decide whether the locks in an arena will have metering information or not. You specify this before creating the arena, to usconfig() (see "Initializing a Shared Arena"). When metering information is enabled, you can retrieve it at any time to find out whether a lock is a bottleneck in a program.
The following functions are provided for using locks:
ussetlock(3P) | Seize a lock, suspending the callerk if necessary, until the lock is available. |
usunsetlock(3P) | Release a lock, making it available for other processes. |
uscsetlock(3P) | Seize a lock if it is available; otherwise return a 1. |
uswsetlock(3P) | Seize a lock, suspending the caller if necessary; takes a specified number of spins as an argument. |
ustestlock(3P) | Test a lock, returning 0 if it is instantaneously available and 1 if it is not available. |
On uniprocessors, none of the functions us[c,w]setlock() spin; if the lock is available they return immediately, and if it is not, they give up the CPU. On multiprocessors, ussettlock() spins for a default number of times before it suspends the process. The function uswsetlock() is the same except that you can specify the number of spins.
Tip: When reading the reference pages cited above, notice that usnewlock() returns a ulock_t object, which is simply a pointer. All the functions that operate on locks take a ulock_t object--not a pointer to a ulock_t. That is, the ulock_t type represents a handle or reference to a lock, not a lock itself. This differs from the treatment of semaphores, which is described in a preceding topic. A process can call usunsetlock() on a lock that is either not locked or locked by another process. In either case, the lock is unlocked. "Double tripping"--calling a set-lock function twice with the same lock--is also permissible. The caller blocks until another process unsets the lock.